package com.jse;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.System.Logger.Level;
import java.net.InetAddress;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Properties;

import com.jse.json.JsonObject;
import com.jse.util.PathMatcher;

public class Jse {

	public final static String VERSION="2.1.0";
	public final static Properties prop=new Properties();
	public final static JsonObject conf=new JsonObject();
	public final static long pid=ProcessHandle.current().pid();
	
	public final static String dir=System.getProperty("user.dir").replace('\\','/');
	public final static String home=System.getProperty("java.home").replace('\\','/');
	public final static String tmpdir=System.getProperty("java.io.tmpdir").replace('\\','/');
	public final static PathMatcher MATCHER=new PathMatcher();
	public final static Cache<String,Object> cache=new Cache<String, Object>();//默认1024
	public final static HashMap<String,String> JSPATH=new HashMap<>();//
	public final static HashMap<String,String> WEBAPP=new HashMap<>();//
	public final static boolean isWindows=File.separatorChar=='\\';
	
	public static String classpath;
	public static File tempDir;//临时目录 web下优先从容器获取
	private static String jspath;//默认执行的js路径
	private static String webapps;//所有web的根 未配置从容器获取
	private static String webapp;//当前web的根 未配置从容器获取
	
	public static String name;//默认项目名为当前目录
	public static String encoding;//默认编码
	public static Charset charset;//默认编码
	public static String ip;//服务器的IP
	public static Class<?> main=Jse.class;//主项目的路径，IOC
	
	public static boolean allowcors=false;//是否允许跨域
	public static String access_control_allow_origin="*";/* 允许跨域的主机地址 */
	public static String access_control_allow_methods="*";/* 允许跨域的请求方法GET, POST, HEAD 等 */
	public static String access_control_max_age="7000";/* 重新预检验跨域的缓存时间 (s) */
	public static String access_control_allow_headers="*";/* 允许跨域的请求头 */
	public static String access_control_allow_credentials="true";/* 是否携带cookie */
	public static String ipCheck;//IP黑白名单 为空则不验证IP
	public static boolean webuploadauto=false;//除/jse/up 是否自动上传
	public static Level LEVEL=Level.INFO;//日志等级
	public static boolean showsql;//显示sql
	public static String ipxdb;//xdb https://gitee.com/lionsoul/ip2region
	public static boolean webdomain;//是否根据域名
	
	
	public static ClassLoader contextClassLoader;
	
	static {
		try {
			classpath=Jse.class.getResource("").getPath();
			if(isWindows){
				if(classpath.charAt(0)=='/')classpath=classpath.substring(1);
				if(classpath.startsWith("file:"))classpath=classpath.substring(6);
			}else {
				if(classpath.startsWith("file:"))classpath=classpath.substring(5);
			}
			if(classpath.endsWith("/com/jse/"))classpath=classpath.substring(0,classpath.length()-9);
			if(classpath.contains("/WEB-INF/lib/")) {
				classpath=classpath.substring(0,classpath.indexOf("/WEB-INF/lib/"))+"/WEB-INF/classes";
			}
			ip=InetAddress.getLocalHost().getHostAddress();
			System.out.println("""
					========================
					jse version:%s
					========================""".formatted(VERSION));
			init();
		}catch(IOException e){e.printStackTrace();}
		
	}
	
	/** 除了第一次 可以改变conf后动态改变 */
	public static void init() {
		if(classpath.indexOf('/')==-1)classpath=dir;
		try {
			if(Files.exists(Path.of(dir,"jse.properties"))){//优先从当前目录取配置
				prop.load(new FileInputStream(dir+"/jse.properties"));conf.putAll(prop);
			}else if(Files.exists(Path.of(classpath,"jse.properties"))){
				prop.load(new FileInputStream(classpath+"/jse.properties"));conf.putAll(prop);
			}else {
				try(var in=Jse.class.getResourceAsStream("/jse.properties")){
					prop.load(in);conf.putAll(prop);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		jspath=conf.getString("jse.jspath");
		if(jspath==null&&Files.exists(Path.of(dir,"src")))jspath=dir+"/src";
		if(jspath==null)jspath=classpath;
		name=jspath.replace("/WEB-INF/classes","").replace("/src","");;
		name=name.substring(name.lastIndexOf("/")+1);
		webapps=conf.getString("jse.webapps");
		webapp=conf.getString("jse.webapp");
		if(webapps!=null&&webapp==null)webapp=webapps+"/web";
		if(webapps==null&&webapp!=null)webapps=webapp.substring(0,webapp.lastIndexOf('/'));
		encoding=conf.getString("jse.encoding","UTF-8");
		charset=Charset.forName(encoding);
		allowcors=Jse.conf.getBoolean("web.cors",false);
		if(allowcors) {
		 access_control_allow_origin=conf.getString("web.cors.Access-Control-Allow-Origin","*");
		 access_control_allow_methods=conf.getString("web.cors.Access-Control-Allow-Methods","*");
		 access_control_max_age=conf.getString("web.cors.Access-Control-Max-Age","7000");
		 access_control_allow_headers=conf.getString("web.cors.Access-Control-Allow-Headers","*");
		 access_control_allow_credentials=conf.getString("web.cors.Access-Control-Allow-Credentials","true");
		}
		ipCheck=conf.getString("jse.ip");
		webuploadauto=conf.getBoolean("web.upload.auto",false);//允许自动上传
		LEVEL=Level.valueOf(conf.getString("jse.log.level","INFO").toUpperCase());//重新指定日志等级
		showsql=conf.getBoolean("jdbc.showsql",true);//测试开启
		ipxdb=conf.getString("jse.ipxdb",dir+"/ip2region.xdb");
		contextClassLoader=Thread.currentThread().getContextClassLoader();
		try {
			if(Files.exists(Path.of(dir,"lib")))
			Compiler.loadJars(Files.list(Path.of(dir,"lib")).map(p->{
				return p.toString().replace('\\','/');
			}).toList());
		} catch (IOException e) {
			e.printStackTrace();
		}
		Ioc.reg("cache",cache);//注册缓存 TODO
		webdomain=conf.getBoolean("jse.webdomain",false);
		if(webdomain) {
			try {
				if(jspath!=null)
				Files.list(Path.of(jspath)).filter(x->Files.isDirectory(x)).forEach((x)->{
					if(x.getFileName().toString().indexOf('.')!=-1) {
						JSPATH.put(x.getFileName().toString(),jspath+"/"+x.getFileName());
					}
				});
				if(webapp!=null)
					Files.list(Path.of(webapp)).filter(x->Files.isDirectory(x)).forEach((x)->{
						if(x.getFileName().toString().indexOf('.')!=-1) {
							WEBAPP.put(x.getFileName().toString(),webapp+"/"+x.getFileName());
						}
				});
			} catch (IOException e) {}
		}
	}
	public static String jspath() {return jspath;}
	public static String webapps() {return webapps;}
	public static String webapp() {return webapp;}
	public static void setJspath(String path) {jspath=path;}
	public static void setWebapps(String path) {webapps=path;}
	public static void setWebapp(String path) {webapp=path;}
	public static String jspath(String serverName) {return JSPATH.getOrDefault(serverName,jspath);}
	public static String webapp(String serverName) {return WEBAPP.getOrDefault(serverName,webapp);}
	
	public static void main(String[] args) throws Exception {
		Server.jdkserver.start();
	}
}
